﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using NabNetLib.Apps.Interface;
using NabNetLib.Apps.NabNetMessage;


namespace NabNetLib
{
    public class Scheduler
    {
        private Dictionary<Plugin, IPlugin> mPluginList = new Dictionary<Plugin,IPlugin>();
        private bool mStarted = false;

        public Scheduler()
        {
            try
            {
                using (nabnetEntities ne = new nabnetEntities())
                {
                    foreach (Plugin pluginDescription in (from p in ne.Plugin select p))
                    {
                        Type pluginType = Type.GetType(pluginDescription.type);
                        if (pluginType != null)
                        {
                            IPlugin concretePlugin = (IPlugin)Activator.CreateInstance(pluginType);
                            mPluginList.Add(pluginDescription, concretePlugin);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Log("Error in Scheduler constructor", ex);
                throw;
            }
        }

        public void StartScheduler()
        {
            if (!mStarted)
            {
                mStarted = true;
                Thread t = new Thread(SchedulerThread);
                t.Start();
            }
        }

        public void StopScheduler()
        {
            mStarted = false;
            Monitor.Pulse(mLocker);
        }



        private object mLocker = new object();
        private Random mRandomizer = new Random((int)(DateTime.Now.Ticks%Int32.MaxValue));


        public void SchedulerThread()
        {
            try
            {
                lock (mLocker)
                {
                    while (mStarted)
                    {
                        Logger.Log(LogType.Debug,"Scheduler wake up");
                        foreach (Plugin pdesc in mPluginList.Keys)
                        {
                            Logger.Log(LogType.Debug, "Scheduler : processing "+pdesc.name);
                            foreach (XmppServerConnection connection in XmppListener.GetXmppConnections(pdesc))
                            {
                                IPlugin p = mPluginList[pdesc];
                                Packet.Packet answer = null;
                                if (p.HandleMessage(new SchedulerMessage() { From = "Scheduler", To = connection.Lapin.serial_number }, ref answer) && answer != null)
                                {
                                    Logger.Log(LogType.Debug, "Scheduler send packet : "+answer);
                                    connection.SendPacketToRabbit(answer);
                                }
                            }
                        }

                        Monitor.Wait(mLocker, mRandomizer.Next(300000, 1800000));
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Log("Error during SchedulerThread", ex);
                throw;
            }
        }
    }
}
